/**
 ******************************************************************************
 * @file    bl70x_usb.c
 * @version V1.0
 * @date
 * @brief   This file is the standard driver c file
 ******************************************************************************
 * @attention
 *
 * <h2><center>&copy; COPYRIGHT(c) 2019 Bouffalo Lab</center></h2>
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *   1. Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright notice,
 *      this list of conditions and the following disclaimer in the documentation
 *      and/or other materials provided with the distribution.
 *   3. Neither the name of Bouffalo Lab nor the names of its contributors
 *      may be used to endorse or promote products derived from this software
 *      without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 ******************************************************************************
 */

#include "bl702_usb.h"
#include "bl702_common.h"
#include "bl702_glb.h"

/** @addtogroup  BL70X_Peripheral_Driver
 *  @{
 */

/** @addtogroup  USB
 *  @{
 */

/** @defgroup  USB_Private_Macros
 *  @{
 */

/*@} end of group USB_Private_Macros */

/** @defgroup  USB_Private_Types
 *  @{
 */

/*@} end of group USB_Private_Types */

/** @defgroup  USB_Private_Variables
 *  @{
 */

/*@} end of group USB_Private_Variables */

/** @defgroup  USB_Global_Variables
 *  @{
 */

/*@} end of group USB_Global_Variables */

/** @defgroup  USB_Private_Fun_Declaration
 *  @{
 */

/*@} end of group USB_Private_Fun_Declaration */

/** @defgroup  USB_Private_Functions
 *  @{
 */

/*@} end of group USB_Private_Functions */

/** @defgroup  USB_Public_Functions
 *  @{
 */

BL_Err_Type USB_Enable(void) {
  uint32_t tmpVal = 0;

  tmpVal = BL_RD_REG(USB_BASE, USB_CONFIG);
  tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_USB_EN);
  BL_WR_REG(USB_BASE, USB_CONFIG, tmpVal);

  return SUCCESS;
}

BL_Err_Type USB_Disable(void) {
  uint32_t tmpVal = 0;

  tmpVal = BL_RD_REG(USB_BASE, USB_CONFIG);
  tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_USB_EN);
  BL_WR_REG(USB_BASE, USB_CONFIG, tmpVal);

  return SUCCESS;
}

BL_Err_Type USB_Set_Config(BL_Fun_Type enable, USB_Config_Type *usbCfg) {
  uint32_t tmpVal = 0;

  /* disable USB first */
  tmpVal = BL_RD_REG(USB_BASE, USB_CONFIG);
  tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_USB_EN);
  BL_WR_REG(USB_BASE, USB_CONFIG, tmpVal);

  /* USB config */
  tmpVal = BL_RD_REG(USB_BASE, USB_CONFIG);

  if (usbCfg->SoftwareCtrl == ENABLE) {
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_USB_EP0_SW_CTRL);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_USB_EP0_SW_ADDR, usbCfg->DeviceAddress);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_USB_EP0_SW_SIZE, usbCfg->EnumMaxPacketSize);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_USB_EP0_SW_NACK_IN, usbCfg->EnumInEn);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_USB_EP0_SW_NACK_OUT, usbCfg->EnumOutEn);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_USB_ROM_DCT_EN, usbCfg->RomBaseDescriptorUsed);
  } else {
    tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_USB_EP0_SW_CTRL);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_USB_ROM_DCT_EN, usbCfg->RomBaseDescriptorUsed);
  }

  BL_WR_REG(USB_BASE, USB_CONFIG, tmpVal);

  /* enable/disable USB */
  tmpVal = BL_RD_REG(USB_BASE, USB_CONFIG);

  if (enable) {
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_USB_EN);
  }

  BL_WR_REG(USB_BASE, USB_CONFIG, tmpVal);

  return SUCCESS;
}

BL_Err_Type USB_Set_Device_Addr(uint8_t addr) {
  uint32_t tmpVal = 0;

  tmpVal = BL_RD_REG(USB_BASE, USB_CONFIG);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_USB_EP0_SW_ADDR, addr);
  BL_WR_REG(USB_BASE, USB_CONFIG, tmpVal);

  return SUCCESS;
}

uint8_t USB_Get_Device_Addr(void) {
  uint32_t tmpVal = 0;

  tmpVal = BL_RD_REG(USB_BASE, USB_CONFIG);

  return BL_GET_REG_BITS_VAL(tmpVal, USB_CR_USB_EP0_SW_ADDR);
}

BL_Err_Type USB_Set_EPx_Xfer_Size(USB_EP_ID epId, uint8_t size) {
  uint32_t tmpVal = 0;

  if (epId == EP_ID0) {
    tmpVal = BL_RD_REG(USB_BASE, USB_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_USB_EP0_SW_SIZE, size);
    BL_WR_REG(USB_BASE, USB_CONFIG, tmpVal);
  } else {
    switch (epId) {
    case EP_ID1:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP1_CONFIG);
      tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP1_SIZE, size);
      BL_WR_REG(USB_BASE, USB_EP1_CONFIG, tmpVal);
      break;

    case EP_ID2:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP2_CONFIG);
      tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP2_SIZE, size);
      BL_WR_REG(USB_BASE, USB_EP2_CONFIG, tmpVal);
      break;

    case EP_ID3:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP3_CONFIG);
      tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP3_SIZE, size);
      BL_WR_REG(USB_BASE, USB_EP3_CONFIG, tmpVal);
      break;

    case EP_ID4:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP4_CONFIG);
      tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP4_SIZE, size);
      BL_WR_REG(USB_BASE, USB_EP4_CONFIG, tmpVal);
      break;

    case EP_ID5:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP5_CONFIG);
      tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP5_SIZE, size);
      BL_WR_REG(USB_BASE, USB_EP5_CONFIG, tmpVal);
      break;

    case EP_ID6:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP6_CONFIG);
      tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP6_SIZE, size);
      BL_WR_REG(USB_BASE, USB_EP6_CONFIG, tmpVal);
      break;

    case EP_ID7:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP7_CONFIG);
      tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP7_SIZE, size);
      BL_WR_REG(USB_BASE, USB_EP7_CONFIG, tmpVal);
      break;

    default:
      break;
    }
  }

  return SUCCESS;
}

BL_Err_Type USB_Set_EPx_IN_Busy(USB_EP_ID epId) {
  uint32_t tmpVal = 0;

  if (epId == EP_ID0) {
    tmpVal = BL_RD_REG(USB_BASE, USB_CONFIG);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_USB_EP0_SW_NACK_IN);
    tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_USB_EP0_SW_STALL);
    BL_WR_REG(USB_BASE, USB_CONFIG, tmpVal);
  } else {
    switch (epId) {
    case EP_ID1:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP1_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP1_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP1_STALL);
      BL_WR_REG(USB_BASE, USB_EP1_CONFIG, tmpVal);
      break;

    case EP_ID2:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP2_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP2_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP2_STALL);
      BL_WR_REG(USB_BASE, USB_EP2_CONFIG, tmpVal);
      break;

    case EP_ID3:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP3_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP3_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP3_STALL);
      BL_WR_REG(USB_BASE, USB_EP3_CONFIG, tmpVal);
      break;

    case EP_ID4:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP4_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP4_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP4_STALL);
      BL_WR_REG(USB_BASE, USB_EP4_CONFIG, tmpVal);
      break;

    case EP_ID5:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP5_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP5_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP5_STALL);
      BL_WR_REG(USB_BASE, USB_EP5_CONFIG, tmpVal);
      break;

    case EP_ID6:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP6_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP6_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP6_STALL);
      BL_WR_REG(USB_BASE, USB_EP6_CONFIG, tmpVal);
      break;

    case EP_ID7:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP7_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP7_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP7_STALL);
      BL_WR_REG(USB_BASE, USB_EP7_CONFIG, tmpVal);
      break;

    default:
      break;
    }
  }

  return SUCCESS;
}

BL_Err_Type USB_Set_EPx_IN_Stall(USB_EP_ID epId) {
  uint32_t tmpVal = 0;

  if (epId == EP_ID0) {
    tmpVal = BL_RD_REG(USB_BASE, USB_CONFIG);
    tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_USB_EP0_SW_NACK_OUT);
    tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_USB_EP0_SW_NACK_IN);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_USB_EP0_SW_STALL);
    BL_WR_REG(USB_BASE, USB_CONFIG, tmpVal);
  } else {
    switch (epId) {
    case EP_ID1:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP1_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP1_NACK);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP1_STALL);
      BL_WR_REG(USB_BASE, USB_EP1_CONFIG, tmpVal);
      break;

    case EP_ID2:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP2_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP2_NACK);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP2_STALL);
      BL_WR_REG(USB_BASE, USB_EP2_CONFIG, tmpVal);
      break;

    case EP_ID3:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP3_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP3_NACK);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP3_STALL);
      BL_WR_REG(USB_BASE, USB_EP3_CONFIG, tmpVal);
      break;

    case EP_ID4:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP4_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP4_NACK);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP4_STALL);
      BL_WR_REG(USB_BASE, USB_EP4_CONFIG, tmpVal);
      break;

    case EP_ID5:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP5_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP5_NACK);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP5_STALL);
      BL_WR_REG(USB_BASE, USB_EP5_CONFIG, tmpVal);
      break;

    case EP_ID6:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP6_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP6_NACK);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP6_STALL);
      BL_WR_REG(USB_BASE, USB_EP6_CONFIG, tmpVal);
      break;

    case EP_ID7:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP7_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP7_NACK);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP7_STALL);
      BL_WR_REG(USB_BASE, USB_EP7_CONFIG, tmpVal);
      break;

    default:
      break;
    }
  }

  return SUCCESS;
}

BL_Err_Type USB_Set_EPx_OUT_Busy(USB_EP_ID epId) {
  uint32_t tmpVal = 0;

  if (epId == EP_ID0) {
    tmpVal = BL_RD_REG(USB_BASE, USB_CONFIG);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_USB_EP0_SW_NACK_OUT);
    tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_USB_EP0_SW_STALL);
    BL_WR_REG(USB_BASE, USB_CONFIG, tmpVal);
  } else {
    switch (epId) {
    case EP_ID1:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP1_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP1_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP1_STALL);
      BL_WR_REG(USB_BASE, USB_EP1_CONFIG, tmpVal);
      break;

    case EP_ID2:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP2_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP2_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP2_STALL);
      BL_WR_REG(USB_BASE, USB_EP2_CONFIG, tmpVal);
      break;

    case EP_ID3:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP3_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP3_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP3_STALL);
      BL_WR_REG(USB_BASE, USB_EP3_CONFIG, tmpVal);
      break;

    case EP_ID4:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP4_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP4_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP4_STALL);
      BL_WR_REG(USB_BASE, USB_EP4_CONFIG, tmpVal);
      break;

    case EP_ID5:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP5_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP5_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP5_STALL);
      BL_WR_REG(USB_BASE, USB_EP5_CONFIG, tmpVal);
      break;

    case EP_ID6:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP6_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP6_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP6_STALL);
      BL_WR_REG(USB_BASE, USB_EP6_CONFIG, tmpVal);
      break;

    case EP_ID7:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP7_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP7_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP7_STALL);
      BL_WR_REG(USB_BASE, USB_EP7_CONFIG, tmpVal);
      break;

    default:
      break;
    }
  }

  return SUCCESS;
}

BL_Err_Type USB_Set_EPx_OUT_Stall(USB_EP_ID epId) {
  uint32_t tmpVal = 0;

  if (epId == EP_ID0) {
    tmpVal = BL_RD_REG(USB_BASE, USB_CONFIG);
    tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_USB_EP0_SW_NACK_OUT);
    tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_USB_EP0_SW_NACK_IN);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_USB_EP0_SW_STALL);
    BL_WR_REG(USB_BASE, USB_CONFIG, tmpVal);
  } else {
    switch (epId) {
    case EP_ID1:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP1_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP1_NACK);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP1_STALL);
      BL_WR_REG(USB_BASE, USB_EP1_CONFIG, tmpVal);
      break;

    case EP_ID2:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP2_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP2_NACK);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP2_STALL);
      BL_WR_REG(USB_BASE, USB_EP2_CONFIG, tmpVal);
      break;

    case EP_ID3:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP3_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP3_NACK);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP3_STALL);
      BL_WR_REG(USB_BASE, USB_EP3_CONFIG, tmpVal);
      break;

    case EP_ID4:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP4_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP4_NACK);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP4_STALL);
      BL_WR_REG(USB_BASE, USB_EP4_CONFIG, tmpVal);
      break;

    case EP_ID5:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP5_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP5_NACK);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP5_STALL);
      BL_WR_REG(USB_BASE, USB_EP5_CONFIG, tmpVal);
      break;

    case EP_ID6:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP6_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP6_NACK);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP6_STALL);
      BL_WR_REG(USB_BASE, USB_EP6_CONFIG, tmpVal);
      break;

    case EP_ID7:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP7_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP7_NACK);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP7_STALL);
      BL_WR_REG(USB_BASE, USB_EP7_CONFIG, tmpVal);
      break;

    default:
      break;
    }
  }

  return SUCCESS;
}

BL_Err_Type USB_Set_EPx_Rdy(USB_EP_ID epId) {
  uint32_t tmpVal = 0;

  if (epId == EP_ID0) {
    tmpVal = BL_RD_REG(USB_BASE, USB_CONFIG);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_USB_EP0_SW_RDY);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_USB_EP0_SW_NACK_OUT);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_USB_EP0_SW_NACK_IN);
    tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_USB_EP0_SW_STALL);
    BL_WR_REG(USB_BASE, USB_CONFIG, tmpVal);
  } else {
    switch (epId) {
    case EP_ID1:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP1_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP1_RDY);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP1_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP1_STALL);
      BL_WR_REG(USB_BASE, USB_EP1_CONFIG, tmpVal);
      break;

    case EP_ID2:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP2_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP2_RDY);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP2_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP2_STALL);
      BL_WR_REG(USB_BASE, USB_EP2_CONFIG, tmpVal);
      break;

    case EP_ID3:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP3_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP3_RDY);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP3_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP3_STALL);
      BL_WR_REG(USB_BASE, USB_EP3_CONFIG, tmpVal);
      break;

    case EP_ID4:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP4_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP4_RDY);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP4_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP4_STALL);
      BL_WR_REG(USB_BASE, USB_EP4_CONFIG, tmpVal);
      break;

    case EP_ID5:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP5_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP5_RDY);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP5_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP5_STALL);
      BL_WR_REG(USB_BASE, USB_EP5_CONFIG, tmpVal);
      break;

    case EP_ID6:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP6_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP6_RDY);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP6_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP6_STALL);
      BL_WR_REG(USB_BASE, USB_EP6_CONFIG, tmpVal);
      break;

    case EP_ID7:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP7_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP7_RDY);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP7_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP7_STALL);
      BL_WR_REG(USB_BASE, USB_EP7_CONFIG, tmpVal);
      break;

    default:
      break;
    }
  }

  return SUCCESS;
}

BL_Sts_Type USB_Is_EPx_RDY_Free(USB_EP_ID epId) {
  uint32_t tmpVal = 0;

  if (epId == EP_ID0) {
    tmpVal = BL_RD_REG(USB_BASE, USB_CONFIG);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_STS_USB_EP0_SW_RDY);
  } else {
    switch (epId) {
    case EP_ID1:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP1_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_STS_EP1_RDY);
      break;

    case EP_ID2:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP2_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_STS_EP2_RDY);
      break;

    case EP_ID3:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP3_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_STS_EP3_RDY);
      break;

    case EP_ID4:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP4_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_STS_EP4_RDY);
      break;

    case EP_ID5:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP5_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_STS_EP5_RDY);
      break;

    case EP_ID6:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP6_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_STS_EP6_RDY);
      break;

    case EP_ID7:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP7_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_STS_EP7_RDY);
      break;

    default:
      break;
    }
  }

  return tmpVal ? RESET : SET;
}

BL_Err_Type USB_Set_EPx_STALL(USB_EP_ID epId) {
  uint32_t tmpVal = 0;

  if (epId == EP_ID0) {
    tmpVal = BL_RD_REG(USB_BASE, USB_CONFIG);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_USB_EP0_SW_STALL);
    BL_WR_REG(USB_BASE, USB_CONFIG, tmpVal);
  } else {
    switch (epId) {
    case EP_ID1:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP1_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP1_STALL);
      BL_WR_REG(USB_BASE, USB_EP1_CONFIG, tmpVal);
      break;

    case EP_ID2:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP2_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP2_STALL);
      BL_WR_REG(USB_BASE, USB_EP2_CONFIG, tmpVal);
      break;

    case EP_ID3:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP3_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP3_STALL);
      BL_WR_REG(USB_BASE, USB_EP3_CONFIG, tmpVal);
      break;

    case EP_ID4:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP4_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP4_STALL);
      BL_WR_REG(USB_BASE, USB_EP4_CONFIG, tmpVal);
      break;

    case EP_ID5:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP5_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP5_STALL);
      BL_WR_REG(USB_BASE, USB_EP5_CONFIG, tmpVal);
      break;

    case EP_ID6:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP6_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP6_STALL);
      BL_WR_REG(USB_BASE, USB_EP6_CONFIG, tmpVal);
      break;

    case EP_ID7:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP7_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP7_STALL);
      BL_WR_REG(USB_BASE, USB_EP7_CONFIG, tmpVal);
      break;

    default:
      break;
    }
  }

  return SUCCESS;
}

BL_Err_Type USB_Clr_EPx_STALL(USB_EP_ID epId) {
  uint32_t tmpVal = 0;

  if (epId == EP_ID0) {
    return SUCCESS;
  } else {
    switch (epId) {
    case EP_ID1:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP1_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP1_STALL);
      BL_WR_REG(USB_BASE, USB_EP1_CONFIG, tmpVal);
      break;

    case EP_ID2:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP2_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP2_STALL);
      BL_WR_REG(USB_BASE, USB_EP2_CONFIG, tmpVal);
      break;

    case EP_ID3:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP3_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP3_STALL);
      BL_WR_REG(USB_BASE, USB_EP3_CONFIG, tmpVal);
      break;

    case EP_ID4:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP4_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP4_STALL);
      BL_WR_REG(USB_BASE, USB_EP4_CONFIG, tmpVal);
      break;

    case EP_ID5:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP5_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP5_STALL);
      BL_WR_REG(USB_BASE, USB_EP5_CONFIG, tmpVal);
      break;

    case EP_ID6:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP6_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP6_STALL);
      BL_WR_REG(USB_BASE, USB_EP6_CONFIG, tmpVal);
      break;

    case EP_ID7:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP7_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP7_STALL);
      BL_WR_REG(USB_BASE, USB_EP7_CONFIG, tmpVal);
      break;

    default:
      break;
    }
  }

  return SUCCESS;
}

BL_Err_Type USB_Set_EPx_Busy(USB_EP_ID epId) {
  uint32_t tmpVal = 0;

  if (epId == EP_ID0) {
    tmpVal = BL_RD_REG(USB_BASE, USB_CONFIG);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_USB_EP0_SW_NACK_IN);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_USB_EP0_SW_NACK_OUT);
    BL_WR_REG(USB_BASE, USB_CONFIG, tmpVal);
  } else {
    switch (epId) {
    case EP_ID1:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP1_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP1_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP1_STALL);
      BL_WR_REG(USB_BASE, USB_EP1_CONFIG, tmpVal);
      break;

    case EP_ID2:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP2_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP2_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP2_STALL);
      BL_WR_REG(USB_BASE, USB_EP2_CONFIG, tmpVal);
      break;

    case EP_ID3:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP3_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP3_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP3_STALL);
      BL_WR_REG(USB_BASE, USB_EP3_CONFIG, tmpVal);
      break;

    case EP_ID4:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP4_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP4_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP4_STALL);
      BL_WR_REG(USB_BASE, USB_EP4_CONFIG, tmpVal);
      break;

    case EP_ID5:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP5_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP5_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP5_STALL);
      BL_WR_REG(USB_BASE, USB_EP5_CONFIG, tmpVal);
      break;

    case EP_ID6:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP6_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP6_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP6_STALL);
      BL_WR_REG(USB_BASE, USB_EP6_CONFIG, tmpVal);
      break;

    case EP_ID7:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP7_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_EP7_NACK);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_EP7_STALL);
      BL_WR_REG(USB_BASE, USB_EP7_CONFIG, tmpVal);
      break;

    default:
      break;
    }
  }

  return SUCCESS;
}

BL_Err_Type USB_Set_EPx_Status(USB_EP_ID epId, USB_EP_STATUS_Type sts) {
  switch (sts) {
  case USB_EP_STATUS_ACK:
    USB_Set_EPx_Rdy(epId);
    break;

  case USB_EP_STATUS_NACK:
    USB_Set_EPx_Busy(epId);
    break;

  case USB_EP_STATUS_STALL:
    USB_Set_EPx_STALL(epId);
    break;

  case USB_EP_STATUS_NSTALL:
    USB_Clr_EPx_STALL(epId);
    break;

  default:
    break;
  }

  return SUCCESS;
}

USB_EP_STATUS_Type USB_Get_EPx_Status(USB_EP_ID epId) {
  uint32_t tmpVal = 0;

  if (epId == EP_ID0) {
    tmpVal = BL_RD_REG(USB_BASE, USB_CONFIG);

    switch ((tmpVal >> 24) & 0x7) {
    case 0:
      return USB_EP_STATUS_ACK;

    case 1:
      return USB_EP_STATUS_STALL;

    case 2:
    case 4:
    case 6:
      return USB_EP_STATUS_NACK;

    default:
      break;
    }
  } else {
    switch (epId) {
    case EP_ID1:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP1_CONFIG);
      break;

    case EP_ID2:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP2_CONFIG);
      break;

    case EP_ID3:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP3_CONFIG);
      break;

    case EP_ID4:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP4_CONFIG);
      break;

    case EP_ID5:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP5_CONFIG);
      break;

    case EP_ID6:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP6_CONFIG);
      break;

    case EP_ID7:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP7_CONFIG);
      break;

    default:
      tmpVal = 0;
      break;
    }

    switch ((tmpVal >> 14) & 0x3) {
    case 0:
      return USB_EP_STATUS_ACK;

    case 1:
      return USB_EP_STATUS_STALL;

    case 2:
      return USB_EP_STATUS_NACK;

    case 3:
    default:
      break;
    }
  }

  return USB_EP_STATUS_NSTALL;
}

BL_Err_Type USB_IntEn(USB_INT_Type intType, uint8_t enable) {
  uint32_t tmpVal = 0;

  if (USB_INT_ALL == intType) {
    if (enable) {
      BL_WR_REG(USB_BASE, USB_INT_EN, USB_INT_TYPE_ALL);
    } else {
      BL_WR_REG(USB_BASE, USB_INT_EN, ~USB_INT_TYPE_ALL);
    }

    return SUCCESS;
  }

  tmpVal = BL_RD_REG(USB_BASE, USB_INT_EN);

  if (enable) {
    tmpVal |= (1 << intType);
  } else {
    tmpVal &= ~(1 << intType);
  }

  BL_WR_REG(USB_BASE, USB_INT_EN, tmpVal);

  return SUCCESS;
}

BL_Err_Type USB_IntMask(USB_INT_Type intType, BL_Mask_Type intMask) {
  uint32_t tmpVal = 0;

  if (USB_INT_ALL == intType) {
    if (intMask != UNMASK) {
      BL_WR_REG(USB_BASE, USB_INT_MASK, USB_INT_TYPE_ALL);
    } else {
      BL_WR_REG(USB_BASE, USB_INT_MASK, ~USB_INT_TYPE_ALL);
    }

    return SUCCESS;
  }

  tmpVal = BL_RD_REG(USB_BASE, USB_INT_MASK);

  if (intMask != UNMASK) {
    tmpVal |= (1 << intType);
  } else {
    tmpVal &= ~(1 << intType);
  }

  BL_WR_REG(USB_BASE, USB_INT_MASK, tmpVal);

  return SUCCESS;
}

BL_Sts_Type USB_Get_IntStatus(USB_INT_Type intType) {
  if (USB_INT_ALL == intType) {
    return BL_RD_REG(USB_BASE, USB_INT_STS) ? SET : RESET;
  }

  return ((BL_RD_REG(USB_BASE, USB_INT_STS) & (1 << intType))) ? SET : RESET;
}

BL_Err_Type USB_Clr_IntStatus(USB_INT_Type intType) {
  uint32_t tmpVal = 0;

  if (USB_INT_ALL == intType) {
    BL_WR_REG(USB_BASE, USB_INT_CLEAR, USB_INT_TYPE_ALL);

    return SUCCESS;
  }

  tmpVal = BL_RD_REG(USB_BASE, USB_INT_CLEAR);
  tmpVal |= (1 << intType);
  BL_WR_REG(USB_BASE, USB_INT_CLEAR, tmpVal);

  return SUCCESS;
}

BL_Err_Type USB_Clr_EPx_IntStatus(USB_EP_ID epId) {
  uint32_t tmpVal = 0;

  tmpVal = BL_RD_REG(USB_BASE, USB_INT_CLEAR);

  if (epId == EP_ID0) {
    tmpVal |= (0x3F << 4);
  } else {
    tmpVal |= (0x3 << (epId * 2 + 8));
  }

  BL_WR_REG(USB_BASE, USB_INT_CLEAR, tmpVal);

  return SUCCESS;
}

uint16_t USB_Get_Frame_Num(void) {
  uint32_t tmpVal = 0;

  tmpVal = BL_RD_REG(USB_BASE, USB_FRAME_NO);

  return tmpVal & 0x7ff;
}

BL_Err_Type USB_Set_EPx_Config(USB_EP_ID epId, EP_Config_Type *epCfg) {
  uint32_t tmpVal = 0;

  if (epId == EP_ID0) {
    return ERROR;
  }

  switch (epId) {
  case EP_ID1:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP1_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP1_TYPE, epCfg->type);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP1_DIR, epCfg->dir);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP1_SIZE, epCfg->EPMaxPacketSize);
    BL_WR_REG(USB_BASE, USB_EP1_CONFIG, tmpVal);
    break;

  case EP_ID2:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP2_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP2_TYPE, epCfg->type);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP2_DIR, epCfg->dir);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP2_SIZE, epCfg->EPMaxPacketSize);
    BL_WR_REG(USB_BASE, USB_EP2_CONFIG, tmpVal);
    break;

  case EP_ID3:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP3_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP3_TYPE, epCfg->type);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP3_DIR, epCfg->dir);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP3_SIZE, epCfg->EPMaxPacketSize);
    BL_WR_REG(USB_BASE, USB_EP3_CONFIG, tmpVal);
    break;

  case EP_ID4:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP4_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP4_TYPE, epCfg->type);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP4_DIR, epCfg->dir);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP4_SIZE, epCfg->EPMaxPacketSize);
    BL_WR_REG(USB_BASE, USB_EP4_CONFIG, tmpVal);
    break;

  case EP_ID5:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP5_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP5_TYPE, epCfg->type);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP5_DIR, epCfg->dir);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP5_SIZE, epCfg->EPMaxPacketSize);
    BL_WR_REG(USB_BASE, USB_EP5_CONFIG, tmpVal);
    break;

  case EP_ID6:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP6_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP6_TYPE, epCfg->type);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP6_DIR, epCfg->dir);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP6_SIZE, epCfg->EPMaxPacketSize);
    BL_WR_REG(USB_BASE, USB_EP6_CONFIG, tmpVal);
    break;

  case EP_ID7:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP7_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP7_TYPE, epCfg->type);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP7_DIR, epCfg->dir);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP7_SIZE, epCfg->EPMaxPacketSize);
    BL_WR_REG(USB_BASE, USB_EP7_CONFIG, tmpVal);
    break;

  default:
    break;
  }

  return SUCCESS;
}

BL_Err_Type USB_Set_EPx_Type(USB_EP_ID epId, EP_XFER_Type type) {
  uint32_t tmpVal = 0;

  if (epId == EP_ID0) {
    return ERROR;
  }

  switch (epId) {
  case EP_ID1:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP1_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP1_TYPE, type);
    BL_WR_REG(USB_BASE, USB_EP1_CONFIG, tmpVal);
    break;

  case EP_ID2:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP2_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP2_TYPE, type);
    BL_WR_REG(USB_BASE, USB_EP2_CONFIG, tmpVal);
    break;

  case EP_ID3:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP3_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP3_TYPE, type);
    BL_WR_REG(USB_BASE, USB_EP3_CONFIG, tmpVal);
    break;

  case EP_ID4:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP4_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP4_TYPE, type);
    BL_WR_REG(USB_BASE, USB_EP4_CONFIG, tmpVal);
    break;

  case EP_ID5:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP5_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP5_TYPE, type);
    BL_WR_REG(USB_BASE, USB_EP5_CONFIG, tmpVal);
    break;

  case EP_ID6:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP6_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP6_TYPE, type);
    BL_WR_REG(USB_BASE, USB_EP6_CONFIG, tmpVal);
    break;

  case EP_ID7:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP7_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP7_TYPE, type);
    BL_WR_REG(USB_BASE, USB_EP7_CONFIG, tmpVal);
    break;

  default:
    break;
  }

  return SUCCESS;
}

EP_XFER_Type USB_Get_EPx_Type(USB_EP_ID epId) {
  uint32_t tmpVal = 0;

  if (epId == EP_ID0) {
    return EP_CTRL;
  }

  switch (epId) {
  case EP_ID1:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP1_CONFIG);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_CR_EP1_TYPE);
    break;

  case EP_ID2:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP2_CONFIG);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_CR_EP2_TYPE);
    break;

  case EP_ID3:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP3_CONFIG);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_CR_EP3_TYPE);
    break;

  case EP_ID4:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP4_CONFIG);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_CR_EP4_TYPE);
    break;

  case EP_ID5:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP5_CONFIG);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_CR_EP5_TYPE);
    break;

  case EP_ID6:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP6_CONFIG);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_CR_EP6_TYPE);
    break;

  case EP_ID7:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP7_CONFIG);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_CR_EP7_TYPE);
    break;

  default:
    break;
  }

  return (EP_XFER_Type)tmpVal;
}

BL_Err_Type USB_Set_EPx_Dir(USB_EP_ID epId, EP_XFER_DIR dir) {
  uint32_t tmpVal = 0;

  if (epId == EP_ID0) {
    return ERROR;
  }

  switch (epId) {
  case EP_ID1:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP1_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP1_DIR, dir);
    BL_WR_REG(USB_BASE, USB_EP1_CONFIG, tmpVal);
    break;

  case EP_ID2:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP2_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP2_DIR, dir);
    BL_WR_REG(USB_BASE, USB_EP2_CONFIG, tmpVal);
    break;

  case EP_ID3:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP3_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP3_DIR, dir);
    BL_WR_REG(USB_BASE, USB_EP3_CONFIG, tmpVal);
    break;

  case EP_ID4:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP4_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP4_DIR, dir);
    BL_WR_REG(USB_BASE, USB_EP4_CONFIG, tmpVal);
    break;

  case EP_ID5:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP5_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP5_DIR, dir);
    BL_WR_REG(USB_BASE, USB_EP5_CONFIG, tmpVal);
    break;

  case EP_ID6:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP6_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP6_DIR, dir);
    BL_WR_REG(USB_BASE, USB_EP6_CONFIG, tmpVal);
    break;

  case EP_ID7:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP7_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP7_DIR, dir);
    BL_WR_REG(USB_BASE, USB_EP7_CONFIG, tmpVal);
    break;

  default:
    break;
  }

  return SUCCESS;
}

EP_XFER_DIR USB_Get_EPx_Dir(USB_EP_ID epId) {
  uint32_t tmpVal = 0;

  if (epId == EP_ID0) {
    return EP_DISABLED;
  }

  switch (epId) {
  case EP_ID1:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP1_CONFIG);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_CR_EP1_DIR);
    break;

  case EP_ID2:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP2_CONFIG);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_CR_EP2_DIR);
    break;

  case EP_ID3:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP3_CONFIG);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_CR_EP3_DIR);
    break;

  case EP_ID4:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP4_CONFIG);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_CR_EP4_DIR);
    break;

  case EP_ID5:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP5_CONFIG);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_CR_EP5_DIR);
    break;

  case EP_ID6:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP6_CONFIG);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_CR_EP6_DIR);
    break;

  case EP_ID7:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP7_CONFIG);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_CR_EP7_DIR);
    break;

  default:
    break;
  }

  return (EP_XFER_DIR)tmpVal;
}

BL_Err_Type USB_Set_EPx_Size(USB_EP_ID epId, uint32_t size) {
  uint32_t tmpVal = 0;

  switch (epId) {
  case EP_ID0:
    tmpVal = BL_RD_REG(USB_BASE, USB_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_USB_EP0_SW_SIZE, size);
    BL_WR_REG(USB_BASE, USB_CONFIG, tmpVal);
    break;

  case EP_ID1:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP1_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP1_SIZE, size);
    BL_WR_REG(USB_BASE, USB_EP1_CONFIG, tmpVal);
    break;

  case EP_ID2:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP2_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP2_SIZE, size);
    BL_WR_REG(USB_BASE, USB_EP2_CONFIG, tmpVal);
    break;

  case EP_ID3:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP3_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP3_SIZE, size);
    BL_WR_REG(USB_BASE, USB_EP3_CONFIG, tmpVal);
    break;

  case EP_ID4:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP4_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP4_SIZE, size);
    BL_WR_REG(USB_BASE, USB_EP4_CONFIG, tmpVal);
    break;

  case EP_ID5:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP5_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP5_SIZE, size);
    BL_WR_REG(USB_BASE, USB_EP5_CONFIG, tmpVal);
    break;

  case EP_ID6:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP6_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP6_SIZE, size);
    BL_WR_REG(USB_BASE, USB_EP6_CONFIG, tmpVal);
    break;

  case EP_ID7:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP7_CONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_EP7_SIZE, size);
    BL_WR_REG(USB_BASE, USB_EP7_CONFIG, tmpVal);
    break;

  default:
    break;
  }

  return SUCCESS;
}

BL_Sts_Type USB_Get_EPx_TX_FIFO_Errors(USB_EP_ID epId, USB_FIFO_ERROR_FLAG_Type errFlag) {
  uint32_t tmpVal = 0;

  if (errFlag == USB_FIFO_ERROR_OVERFLOW) {
    switch (epId) {
    case EP_ID0:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP0_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP0_TX_FIFO_OVERFLOW);
      break;

    case EP_ID1:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP1_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP1_TX_FIFO_OVERFLOW);
      break;

    case EP_ID2:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP2_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP2_TX_FIFO_OVERFLOW);
      break;

    case EP_ID3:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP3_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP3_TX_FIFO_OVERFLOW);
      break;

    case EP_ID4:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP4_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP4_TX_FIFO_OVERFLOW);
      break;

    case EP_ID5:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP5_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP5_TX_FIFO_OVERFLOW);
      break;

    case EP_ID6:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP6_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP6_TX_FIFO_OVERFLOW);
      break;

    case EP_ID7:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP7_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP7_TX_FIFO_OVERFLOW);
      break;

    default:
      tmpVal = 0;
      break;
    }
  } else {
    switch (epId) {
    case EP_ID0:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP0_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP0_TX_FIFO_UNDERFLOW);
      break;

    case EP_ID1:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP1_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP1_TX_FIFO_UNDERFLOW);
      break;

    case EP_ID2:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP2_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP2_TX_FIFO_UNDERFLOW);
      break;

    case EP_ID3:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP3_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP3_TX_FIFO_UNDERFLOW);
      break;

    case EP_ID4:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP4_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP4_TX_FIFO_UNDERFLOW);
      break;

    case EP_ID5:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP5_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP5_TX_FIFO_UNDERFLOW);
      break;

    case EP_ID6:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP6_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP6_TX_FIFO_UNDERFLOW);
      break;

    case EP_ID7:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP7_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP7_TX_FIFO_UNDERFLOW);
      break;

    default:
      tmpVal = 0;
      break;
    }
  }

  return tmpVal ? SET : RESET;
}

BL_Sts_Type USB_Get_EPx_RX_FIFO_Errors(USB_EP_ID epId, USB_FIFO_ERROR_FLAG_Type errFlag) {
  uint32_t tmpVal = 0;

  if (errFlag == USB_FIFO_ERROR_OVERFLOW) {
    switch (epId) {
    case EP_ID0:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP0_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP0_RX_FIFO_OVERFLOW);
      break;

    case EP_ID1:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP1_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP1_RX_FIFO_OVERFLOW);
      break;

    case EP_ID2:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP2_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP2_RX_FIFO_OVERFLOW);
      break;

    case EP_ID3:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP3_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP3_RX_FIFO_OVERFLOW);
      break;

    case EP_ID4:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP4_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP4_RX_FIFO_OVERFLOW);
      break;

    case EP_ID5:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP5_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP5_RX_FIFO_OVERFLOW);
      break;

    case EP_ID6:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP6_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP6_RX_FIFO_OVERFLOW);
      break;

    case EP_ID7:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP7_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP7_RX_FIFO_OVERFLOW);
      break;

    default:
      tmpVal = 0;
      break;
    }
  } else {
    switch (epId) {
    case EP_ID0:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP0_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP0_RX_FIFO_UNDERFLOW);
      break;

    case EP_ID1:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP1_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP1_RX_FIFO_UNDERFLOW);
      break;

    case EP_ID2:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP2_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP2_RX_FIFO_UNDERFLOW);
      break;

    case EP_ID3:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP3_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP3_RX_FIFO_UNDERFLOW);
      break;

    case EP_ID4:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP4_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP4_RX_FIFO_UNDERFLOW);
      break;

    case EP_ID5:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP5_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP5_RX_FIFO_UNDERFLOW);
      break;

    case EP_ID6:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP6_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP6_RX_FIFO_UNDERFLOW);
      break;

    case EP_ID7:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP7_FIFO_CONFIG);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP7_RX_FIFO_UNDERFLOW);
      break;

    default:
      tmpVal = 0;
      break;
    }
  }

  return tmpVal ? SET : RESET;
}

BL_Err_Type USB_Clr_EPx_TX_FIFO_Errors(USB_EP_ID epId) {
  uint32_t tmpVal = 0;

  switch (epId) {
  case EP_ID0:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP0_FIFO_CONFIG);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP0_TX_FIFO_CLR);
    BL_WR_REG(USB_BASE, USB_EP0_FIFO_CONFIG, tmpVal);
    break;

  case EP_ID1:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP1_FIFO_CONFIG);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP1_TX_FIFO_CLR);
    BL_WR_REG(USB_BASE, USB_EP1_FIFO_CONFIG, tmpVal);
    break;

  case EP_ID2:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP2_FIFO_CONFIG);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP2_TX_FIFO_CLR);
    BL_WR_REG(USB_BASE, USB_EP2_FIFO_CONFIG, tmpVal);
    break;

  case EP_ID3:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP3_FIFO_CONFIG);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP3_TX_FIFO_CLR);
    BL_WR_REG(USB_BASE, USB_EP3_FIFO_CONFIG, tmpVal);
    break;

  case EP_ID4:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP4_FIFO_CONFIG);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP4_TX_FIFO_CLR);
    BL_WR_REG(USB_BASE, USB_EP4_FIFO_CONFIG, tmpVal);
    break;

  case EP_ID5:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP5_FIFO_CONFIG);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP5_TX_FIFO_CLR);
    BL_WR_REG(USB_BASE, USB_EP5_FIFO_CONFIG, tmpVal);
    break;

  case EP_ID6:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP6_FIFO_CONFIG);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP6_TX_FIFO_CLR);
    BL_WR_REG(USB_BASE, USB_EP6_FIFO_CONFIG, tmpVal);
    break;

  case EP_ID7:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP7_FIFO_CONFIG);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP7_TX_FIFO_CLR);
    BL_WR_REG(USB_BASE, USB_EP7_FIFO_CONFIG, tmpVal);
    break;

  default:
    break;
  }

  return SUCCESS;
}

BL_Err_Type USB_Clr_EPx_RX_FIFO_Errors(USB_EP_ID epId) {
  uint32_t tmpVal = 0;

  switch (epId) {
  case EP_ID0:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP0_FIFO_CONFIG);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP0_RX_FIFO_CLR);
    BL_WR_REG(USB_BASE, USB_EP0_FIFO_CONFIG, tmpVal);
    break;

  case EP_ID1:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP1_FIFO_CONFIG);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP1_RX_FIFO_CLR);
    BL_WR_REG(USB_BASE, USB_EP1_FIFO_CONFIG, tmpVal);
    break;

  case EP_ID2:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP2_FIFO_CONFIG);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP2_RX_FIFO_CLR);
    BL_WR_REG(USB_BASE, USB_EP2_FIFO_CONFIG, tmpVal);
    break;

  case EP_ID3:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP3_FIFO_CONFIG);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP3_RX_FIFO_CLR);
    BL_WR_REG(USB_BASE, USB_EP3_FIFO_CONFIG, tmpVal);
    break;

  case EP_ID4:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP4_FIFO_CONFIG);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP4_RX_FIFO_CLR);
    BL_WR_REG(USB_BASE, USB_EP4_FIFO_CONFIG, tmpVal);
    break;

  case EP_ID5:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP5_FIFO_CONFIG);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP5_RX_FIFO_CLR);
    BL_WR_REG(USB_BASE, USB_EP5_FIFO_CONFIG, tmpVal);
    break;

  case EP_ID6:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP6_FIFO_CONFIG);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP6_RX_FIFO_CLR);
    BL_WR_REG(USB_BASE, USB_EP6_FIFO_CONFIG, tmpVal);
    break;

  case EP_ID7:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP7_FIFO_CONFIG);
    tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP7_RX_FIFO_CLR);
    BL_WR_REG(USB_BASE, USB_EP7_FIFO_CONFIG, tmpVal);
    break;

  default:
    break;
  }

  return SUCCESS;
}

BL_Err_Type USB_EPx_Write_Data_To_FIFO(USB_EP_ID epId, uint8_t *pData, uint16_t len) {
  uint32_t timeout = 0x00FFFFFF;

  while ((!USB_Is_EPx_RDY_Free(epId)) && timeout) {
    timeout--;
  }

  if (!timeout) {
    return ERROR;
  }

  if (len == 1) {
    USB_Set_EPx_Xfer_Size(EP_ID0, 1);
  } else {
    USB_Set_EPx_Xfer_Size(EP_ID0, 64);
  }

  for (uint16_t i = 0; i < len; i++) {
    switch (epId) {
    case EP_ID0:
      BL_WR_REG(USB_BASE, USB_EP0_TX_FIFO_WDATA, pData[i]);
      break;

    case EP_ID1:
      BL_WR_REG(USB_BASE, USB_EP1_TX_FIFO_WDATA, pData[i]);
      break;

    case EP_ID2:
      BL_WR_REG(USB_BASE, USB_EP2_TX_FIFO_WDATA, pData[i]);
      break;

    case EP_ID3:
      BL_WR_REG(USB_BASE, USB_EP3_TX_FIFO_WDATA, pData[i]);
      break;

    case EP_ID4:
      BL_WR_REG(USB_BASE, USB_EP4_TX_FIFO_WDATA, pData[i]);
      break;

    case EP_ID5:
      BL_WR_REG(USB_BASE, USB_EP5_TX_FIFO_WDATA, pData[i]);
      break;

    case EP_ID6:
      BL_WR_REG(USB_BASE, USB_EP6_TX_FIFO_WDATA, pData[i]);
      break;

    case EP_ID7:
      BL_WR_REG(USB_BASE, USB_EP7_TX_FIFO_WDATA, pData[i]);
      break;

    default:
      break;
    }
  }

  return SUCCESS;
}

BL_Err_Type USB_EPx_Read_Data_From_FIFO(USB_EP_ID epId, uint8_t *pBuff, uint16_t len) {
  for (uint16_t i = 0; i < len; i++) {
    switch (epId) {
    case EP_ID0:
      pBuff[i] = (uint8_t)BL_RD_REG(USB_BASE, USB_EP0_RX_FIFO_RDATA);
      break;

    case EP_ID1:
      pBuff[i] = (uint8_t)BL_RD_REG(USB_BASE, USB_EP1_RX_FIFO_RDATA);
      break;

    case EP_ID2:
      pBuff[i] = (uint8_t)BL_RD_REG(USB_BASE, USB_EP2_RX_FIFO_RDATA);
      break;

    case EP_ID3:
      pBuff[i] = (uint8_t)BL_RD_REG(USB_BASE, USB_EP3_RX_FIFO_RDATA);
      break;

    case EP_ID4:
      pBuff[i] = (uint8_t)BL_RD_REG(USB_BASE, USB_EP4_RX_FIFO_RDATA);
      break;

    case EP_ID5:
      pBuff[i] = (uint8_t)BL_RD_REG(USB_BASE, USB_EP5_RX_FIFO_RDATA);
      break;

    case EP_ID6:
      pBuff[i] = (uint8_t)BL_RD_REG(USB_BASE, USB_EP6_RX_FIFO_RDATA);
      break;

    case EP_ID7:
      pBuff[i] = (uint8_t)BL_RD_REG(USB_BASE, USB_EP7_RX_FIFO_RDATA);
      break;

    default:
      break;
    }
  }

  return SUCCESS;
}

BL_Err_Type USB_Set_EPx_TX_DMA_Interface_Config(USB_EP_ID epId, BL_Fun_Type newState) {
  uint32_t tmpVal = 0;

  if (newState == ENABLE) {
    switch (epId) {
    case EP_ID0:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP0_FIFO_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP0_DMA_TX_EN);
      BL_WR_REG(USB_BASE, USB_EP0_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID1:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP1_FIFO_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP1_DMA_TX_EN);
      BL_WR_REG(USB_BASE, USB_EP1_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID2:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP2_FIFO_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP2_DMA_TX_EN);
      BL_WR_REG(USB_BASE, USB_EP2_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID3:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP3_FIFO_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP3_DMA_TX_EN);
      BL_WR_REG(USB_BASE, USB_EP3_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID4:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP4_FIFO_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP4_DMA_TX_EN);
      BL_WR_REG(USB_BASE, USB_EP4_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID5:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP5_FIFO_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP5_DMA_TX_EN);
      BL_WR_REG(USB_BASE, USB_EP5_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID6:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP6_FIFO_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP6_DMA_TX_EN);
      BL_WR_REG(USB_BASE, USB_EP6_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID7:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP7_FIFO_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP7_DMA_TX_EN);
      BL_WR_REG(USB_BASE, USB_EP7_FIFO_CONFIG, tmpVal);
      break;

    default:
      break;
    }
  } else {
    switch (epId) {
    case EP_ID0:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP0_FIFO_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_EP0_DMA_TX_EN);
      BL_WR_REG(USB_BASE, USB_EP0_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID1:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP1_FIFO_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_EP1_DMA_TX_EN);
      BL_WR_REG(USB_BASE, USB_EP1_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID2:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP2_FIFO_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_EP2_DMA_TX_EN);
      BL_WR_REG(USB_BASE, USB_EP2_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID3:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP3_FIFO_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_EP3_DMA_TX_EN);
      BL_WR_REG(USB_BASE, USB_EP3_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID4:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP4_FIFO_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_EP4_DMA_TX_EN);
      BL_WR_REG(USB_BASE, USB_EP4_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID5:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP5_FIFO_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_EP5_DMA_TX_EN);
      BL_WR_REG(USB_BASE, USB_EP5_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID6:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP6_FIFO_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_EP6_DMA_TX_EN);
      BL_WR_REG(USB_BASE, USB_EP6_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID7:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP7_FIFO_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_EP7_DMA_TX_EN);
      BL_WR_REG(USB_BASE, USB_EP7_FIFO_CONFIG, tmpVal);
      break;

    default:
      break;
    }
  }

  return SUCCESS;
}

BL_Err_Type USB_Set_EPx_RX_DMA_Interface_Config(USB_EP_ID epId, BL_Fun_Type newState) {
  uint32_t tmpVal = 0;

  if (newState == ENABLE) {
    switch (epId) {
    case EP_ID0:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP0_FIFO_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP0_DMA_RX_EN);
      BL_WR_REG(USB_BASE, USB_EP0_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID1:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP1_FIFO_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP1_DMA_RX_EN);
      BL_WR_REG(USB_BASE, USB_EP1_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID2:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP2_FIFO_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP2_DMA_RX_EN);
      BL_WR_REG(USB_BASE, USB_EP2_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID3:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP3_FIFO_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP3_DMA_RX_EN);
      BL_WR_REG(USB_BASE, USB_EP3_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID4:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP4_FIFO_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP4_DMA_RX_EN);
      BL_WR_REG(USB_BASE, USB_EP4_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID5:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP5_FIFO_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP5_DMA_RX_EN);
      BL_WR_REG(USB_BASE, USB_EP5_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID6:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP6_FIFO_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP6_DMA_RX_EN);
      BL_WR_REG(USB_BASE, USB_EP6_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID7:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP7_FIFO_CONFIG);
      tmpVal = BL_SET_REG_BIT(tmpVal, USB_EP7_DMA_RX_EN);
      BL_WR_REG(USB_BASE, USB_EP7_FIFO_CONFIG, tmpVal);
      break;

    default:
      break;
    }
  } else {
    switch (epId) {
    case EP_ID0:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP0_FIFO_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_EP0_DMA_RX_EN);
      BL_WR_REG(USB_BASE, USB_EP0_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID1:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP1_FIFO_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_EP1_DMA_RX_EN);
      BL_WR_REG(USB_BASE, USB_EP1_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID2:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP2_FIFO_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_EP2_DMA_RX_EN);
      BL_WR_REG(USB_BASE, USB_EP2_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID3:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP3_FIFO_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_EP3_DMA_RX_EN);
      BL_WR_REG(USB_BASE, USB_EP3_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID4:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP4_FIFO_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_EP4_DMA_RX_EN);
      BL_WR_REG(USB_BASE, USB_EP4_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID5:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP5_FIFO_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_EP5_DMA_RX_EN);
      BL_WR_REG(USB_BASE, USB_EP5_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID6:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP6_FIFO_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_EP6_DMA_RX_EN);
      BL_WR_REG(USB_BASE, USB_EP6_FIFO_CONFIG, tmpVal);
      break;

    case EP_ID7:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP7_FIFO_CONFIG);
      tmpVal = BL_CLR_REG_BIT(tmpVal, USB_EP7_DMA_RX_EN);
      BL_WR_REG(USB_BASE, USB_EP7_FIFO_CONFIG, tmpVal);
      break;

    default:
      break;
    }
  }

  return SUCCESS;
}

BL_Err_Type USB_EPx_Write_Data_To_FIFO_DMA(USB_EP_ID epId, uint8_t *pData, uint16_t len) {
  /* not yet implemented */

  return SUCCESS;
}

BL_Err_Type USB_EPx_Read_Data_From_FIFO_DMA(USB_EP_ID epId, uint8_t *pBuff, uint16_t len) {
  /* not yet implemented */

  return SUCCESS;
}

uint16_t USB_Get_EPx_TX_FIFO_CNT(USB_EP_ID epId) {
  uint32_t tmpVal = 0;

  switch (epId) {
  case EP_ID0:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP0_FIFO_STATUS);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP0_TX_FIFO_CNT);
    break;

  case EP_ID1:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP1_FIFO_STATUS);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP1_TX_FIFO_CNT);
    break;

  case EP_ID2:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP2_FIFO_STATUS);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP2_TX_FIFO_CNT);
    break;

  case EP_ID3:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP3_FIFO_STATUS);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP3_TX_FIFO_CNT);
    break;

  case EP_ID4:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP4_FIFO_STATUS);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP4_TX_FIFO_CNT);
    break;

  case EP_ID5:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP5_FIFO_STATUS);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP5_TX_FIFO_CNT);
    break;

  case EP_ID6:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP6_FIFO_STATUS);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP6_TX_FIFO_CNT);
    break;

  case EP_ID7:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP7_FIFO_STATUS);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP7_TX_FIFO_CNT);
    break;

  default:
    tmpVal = 0;
    break;
  }

  return tmpVal;
}

uint16_t USB_Get_EPx_RX_FIFO_CNT(USB_EP_ID epId) {
  uint32_t tmpVal = 0;

  switch (epId) {
  case EP_ID0:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP0_FIFO_STATUS);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP0_RX_FIFO_CNT);
    break;

  case EP_ID1:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP1_FIFO_STATUS);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP1_RX_FIFO_CNT);
    break;

  case EP_ID2:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP2_FIFO_STATUS);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP2_RX_FIFO_CNT);
    break;

  case EP_ID3:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP3_FIFO_STATUS);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP3_RX_FIFO_CNT);
    break;

  case EP_ID4:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP4_FIFO_STATUS);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP4_RX_FIFO_CNT);
    break;

  case EP_ID5:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP5_FIFO_STATUS);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP5_RX_FIFO_CNT);
    break;

  case EP_ID6:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP6_FIFO_STATUS);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP6_RX_FIFO_CNT);
    break;

  case EP_ID7:
    tmpVal = BL_RD_REG(USB_BASE, USB_EP7_FIFO_STATUS);
    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP7_RX_FIFO_CNT);
    break;

  default:
    tmpVal = 0;
    break;
  }

  return tmpVal;
}

BL_Sts_Type USB_Get_EPx_TX_FIFO_Status(USB_EP_ID epId, USB_FIFO_STATUS_Type sts) {
  uint32_t tmpVal = 0;

  if (sts == USB_FIFO_EMPTY) {
    switch (epId) {
    case EP_ID0:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP0_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP0_TX_FIFO_EMPTY);
      break;

    case EP_ID1:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP1_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP1_TX_FIFO_EMPTY);
      break;

    case EP_ID2:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP2_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP2_TX_FIFO_EMPTY);
      break;

    case EP_ID3:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP3_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP3_TX_FIFO_EMPTY);
      break;

    case EP_ID4:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP4_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP4_TX_FIFO_EMPTY);
      break;

    case EP_ID5:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP5_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP5_TX_FIFO_EMPTY);
      break;

    case EP_ID6:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP6_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP6_TX_FIFO_EMPTY);
      break;

    case EP_ID7:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP7_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP7_TX_FIFO_EMPTY);
      break;

    default:
      tmpVal = 0;
      break;
    }
  } else {
    switch (epId) {
    case EP_ID0:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP0_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP0_TX_FIFO_FULL);
      break;

    case EP_ID1:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP1_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP1_TX_FIFO_FULL);
      break;

    case EP_ID2:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP2_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP2_TX_FIFO_FULL);
      break;

    case EP_ID3:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP3_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP3_TX_FIFO_FULL);
      break;

    case EP_ID4:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP4_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP4_TX_FIFO_FULL);
      break;

    case EP_ID5:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP5_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP5_TX_FIFO_FULL);
      break;

    case EP_ID6:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP6_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP6_TX_FIFO_FULL);
      break;

    case EP_ID7:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP7_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP7_TX_FIFO_FULL);
      break;

    default:
      tmpVal = 0;
      break;
    }
  }

  return tmpVal ? SET : RESET;
}

BL_Sts_Type USB_Get_EPx_RX_FIFO_Status(USB_EP_ID epId, USB_FIFO_STATUS_Type sts) {
  uint32_t tmpVal = 0;

  if (sts == USB_FIFO_EMPTY) {
    switch (epId) {
    case EP_ID0:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP0_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP0_RX_FIFO_EMPTY);
      break;

    case EP_ID1:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP1_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP1_RX_FIFO_EMPTY);
      break;

    case EP_ID2:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP2_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP2_RX_FIFO_EMPTY);
      break;

    case EP_ID3:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP3_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP3_RX_FIFO_EMPTY);
      break;

    case EP_ID4:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP4_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP4_RX_FIFO_EMPTY);
      break;

    case EP_ID5:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP5_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP5_RX_FIFO_EMPTY);
      break;

    case EP_ID6:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP6_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP6_RX_FIFO_EMPTY);
      break;

    case EP_ID7:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP7_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP7_RX_FIFO_EMPTY);
      break;

    default:
      tmpVal = 0;
      break;
    }
  } else {
    switch (epId) {
    case EP_ID0:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP0_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP0_RX_FIFO_FULL);
      break;

    case EP_ID1:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP1_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP1_RX_FIFO_FULL);
      break;

    case EP_ID2:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP2_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP2_RX_FIFO_FULL);
      break;

    case EP_ID3:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP3_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP3_RX_FIFO_FULL);
      break;

    case EP_ID4:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP4_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP4_RX_FIFO_FULL);
      break;

    case EP_ID5:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP5_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP5_RX_FIFO_FULL);
      break;

    case EP_ID6:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP6_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP6_RX_FIFO_FULL);
      break;

    case EP_ID7:
      tmpVal = BL_RD_REG(USB_BASE, USB_EP7_FIFO_STATUS);
      tmpVal = BL_GET_REG_BITS_VAL(tmpVal, USB_EP7_RX_FIFO_FULL);
      break;

    default:
      tmpVal = 0;
      break;
    }
  }

  return tmpVal ? SET : RESET;
}

BL_Err_Type USB_Set_Internal_PullUp_Config(BL_Fun_Type newState) {
  uint32_t tmpVal = 0;

  /* recommended: fclk<=160MHz, bclk<=80MHz */
  tmpVal = BL_RD_REG(GLB_BASE, GLB_USB_XCVR);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, GLB_USB_ENUM, newState);
  BL_WR_REG(GLB_BASE, GLB_USB_XCVR, tmpVal);

  return SUCCESS;
}

BL_Sts_Type USB_Get_LPM_Status(void) {
  uint32_t tmpVal = 0;

  tmpVal = BL_RD_REG(USB_BASE, USB_LPM_CONFIG);

  return BL_GET_REG_BITS_VAL(tmpVal, USB_STS_LPM) ? SET : RESET;
}

uint16_t USB_Get_LPM_Packet_Attr(void) {
  uint32_t tmpVal = 0;

  tmpVal = BL_RD_REG(USB_BASE, USB_LPM_CONFIG);

  return BL_GET_REG_BITS_VAL(tmpVal, USB_STS_LPM_ATTR);
}

BL_Err_Type USB_Set_LPM_Default_Response(USB_LPM_DEFAULT_RESP_Type defaultResp) {
  uint32_t tmpVal = 0;

  tmpVal = BL_RD_REG(USB_BASE, USB_LPM_CONFIG);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_LPM_RESP, defaultResp);
  BL_WR_REG(USB_BASE, USB_LPM_CONFIG, tmpVal);

  tmpVal = BL_RD_REG(USB_BASE, USB_LPM_CONFIG);
  tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_LPM_RESP_UPD);
  BL_WR_REG(USB_BASE, USB_LPM_CONFIG, tmpVal);

  return SUCCESS;
}

BL_Err_Type USB_LPM_Enable(void) {
  uint32_t tmpVal = 0;

  tmpVal = BL_RD_REG(USB_BASE, USB_LPM_CONFIG);
  tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_LPM_EN);
  BL_WR_REG(USB_BASE, USB_LPM_CONFIG, tmpVal);

  return SUCCESS;
}

BL_Err_Type USB_LPM_Disable(void) {
  uint32_t tmpVal = 0;

  tmpVal = BL_RD_REG(USB_BASE, USB_LPM_CONFIG);
  tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CR_LPM_EN);
  BL_WR_REG(USB_BASE, USB_LPM_CONFIG, tmpVal);

  return SUCCESS;
}

BL_Err_Type USB_Device_Output_K_State(uint16_t stateWidth) {
  uint32_t tmpVal = 0;

  CHECK_PARAM((stateWidth <= 0x7FF));

  tmpVal = BL_RD_REG(USB_BASE, USB_RESUME_CONFIG);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_CR_RES_WIDTH, stateWidth);
  BL_WR_REG(USB_BASE, USB_RESUME_CONFIG, tmpVal);

  tmpVal = BL_RD_REG(USB_BASE, USB_RESUME_CONFIG);
  tmpVal = BL_SET_REG_BIT(tmpVal, USB_CR_RES_TRIG);
  BL_WR_REG(USB_BASE, USB_RESUME_CONFIG, tmpVal);

  return SUCCESS;
}

uint8_t USB_Get_Current_Packet_PID(void) {
  uint32_t tmpVal = 0;

  tmpVal = BL_RD_REG(USB_BASE, USB_FRAME_NO);

  return BL_GET_REG_BITS_VAL(tmpVal, USB_STS_PID);
}

uint8_t USB_Get_Current_Packet_EP(void) {
  uint32_t tmpVal = 0;

  tmpVal = BL_RD_REG(USB_BASE, USB_FRAME_NO);

  return BL_GET_REG_BITS_VAL(tmpVal, USB_STS_EP_NO);
}

BL_Sts_Type USB_Get_Error_Status(USB_ERROR_Type err) {
  uint32_t tmpVal = 0;

  tmpVal = BL_RD_REG(USB_BASE, USB_ERROR);

  return tmpVal & (1 << err) ? SET : RESET;
}

BL_Err_Type USB_Clr_Error_Status(USB_ERROR_Type err) {
  uint32_t tmpVal = 0;

  tmpVal = BL_RD_REG(USB_BASE, USB_INT_CLEAR);
  tmpVal |= (1 << USB_INT_ERROR);
  BL_WR_REG(USB_BASE, USB_INT_CLEAR, tmpVal);

  return SUCCESS;
}

BL_Err_Type USB_Clr_RstEndIntStatus(void) {
  uint32_t tmpVal = 0;

  tmpVal = BL_RD_REG(USB_BASE, USB_INT_CLEAR);
  tmpVal |= (1 << 27);
  BL_WR_REG(USB_BASE, USB_INT_CLEAR, tmpVal);

  return SUCCESS;
}

/*@} end of group USB_Public_Functions */

/*@} end of group USB */

/*@} end of group BL70X_Peripheral_Driver */
